/* 
 * yulu-keji.com js base library 
 * copyright@ www.yulu-keji.com
 * 
 * events:
 * 		yulu.ui.rpeater.init
 * 		yulu.ui.repeater.rendering [contents, list, $data]
 * 		yulu.ui.repeater.item.created [contents[i], list[i], $data]
 * 		yulu.ui.repeater.rendered [contents, list, $data]
 * 
 * 		yulu.ajax.success [data, textStatus, jqXHR]
 * 		yulu.ajax.error [jqXHR, ajaxSettings, thrownError]
 * 		yulu.ajax.complete [jqXHR, textStatus]
 * 		yulu.ajax.begin, [ajaxOptions]
 * 		yulu.ui.ajaxrpeater.init, ajaxRepeater
 * */

(function ($, yulu) {

    var ui = yulu("ui"),
        core = yulu("core"),
        ajax = yulu("ajax"),
        config = yulu("ui.config.defaults"),
        tableConfig = yulu("ui.config.defaults.table"),
        listConfig = yulu("ui.config.defaults.list"),
        treeConfig = yulu("ui.config.defaults.tree"),
        components = yulu("ui.components"),
        plugins = yulu("ui.plugins");


    tableConfig.template = "[data-toggle=yulu-table-template],[data-toggle=yulu-template]";
    tableConfig.includetag = true;	// 是否包含标签体
    tableConfig.replace = true;		// 重新调用渲染时, true: 替换, false: 追加
    tableConfig.append = true;		// true: 末尾追加 false: 开头追加

    listConfig = config["list"] = $.extend(core.objectClone(tableConfig), {template: "[data-toggle=yulu-list-item-template],[data-toggle=yulu-template]"});
    treeConfig = config["tree"] = $.extend(core.objectClone(tableConfig), {template: "[data-toggle=yulu-tree-node-template],[data-toggle=yulu-template]"});

    ui.templates = {}
    ui.templates.defaults = ui.templates.format = function (tmpl, data) {
        return yulu.core.stringFormat(tmpl, data);
    }

    ui.templates.artTemplate = function (tmpl, data) {
        if (window.template && window.template.compile) {
            return window.template.compile(tmpl)(data);
        } else {
            throw Error("required artTemplate.js");
        }
    }

    ui.templates.baidu = function (tmpl, data) {
        if (window.baidu && window.baidu.template) {
            return window.baidu.template(tmpl, data);
        } else {
            throw Error("required baidu.template");
        }
    }

    var repeater = ui.repeater = function (options) {
        /**
         * list: Array
         * template: string, selector, dom, jQuery
         * container: selector, dom, jQuery
         * append: boolean[default true]
         * replace: boolean[default true]
         * data: object (extends data)
         * templateFactory: string
         */
        options = $.extend({template: "", append: true, replace: true, templateFactory: "defaults"}, options);
        var list = options.list || [],
            tmplHtml = options.template || "",
            $container = $(options.container),
            append = !!options.append,
            replace = !!options.replace,
            $data = options.data,
            factory = ui.templates[options.templateFactory];

        var contents = [];

        $(list).each(function(index, item) {
            var data = item;
            data["$index"] = index;
            data["$data"] = $data;
            contents.push($(factory(tmplHtml, data)));
        });
        if (replace) {
            var repeaters = $container.data("yulu-ui-repeaters") || [];
            $(repeaters).each(function() {
                $(this).remove();
            });
            for (var i = 0; i < contents.length; i++) {
                contents[i] = $(contents[i]);
            }
            $container.data("yulu-ui-repeaters", contents);
        }

        $container.trigger("yulu.ui.repeater.rendering", [contents, list, $data]);
        if (append) {
            for (var i = 0; i < contents.length; i++) {
                $container.append(contents[i]);
                $container.trigger("yulu.ui.repeater.item.created", [contents[i], list[i], $data]);
            }
        } else {
            for (var i = contents.length - 1; i >= 0; i--) {
                $container.prepend(contents[i])
                $container.trigger("yulu.ui.repeater.item.created", [contents[i], list[i], $data]);
            }
        }
        $container.trigger("yulu.ui.repeater.rendered", [contents, list, $data]);
    }

    var Repeater = components.Repeater = function (container, template, append, replace, templateFactory) {
        var self = this;
        installPlugins($(container));

        $(container).trigger("yulu.ui.repeater.init", self);
        this.getTemplate = function () {
            return template;
        }
        this.getContainer = function () {
            return container;
        }
        this.fnRemoveItems = function () {
            var repeaters = $(container).data("yulu-ui-repeaters") || [];
            $(repeaters).each(function () {
                $(this).remove();
            });
        }

        var cacheData;
        var cacheList;
        this.fnRender = function (list, data) {
            var options = {}
            cacheList = options.list = list;
            cacheData = options.data = data;
            options.append = append;
            options.replace = replace;
            options.template = template;
            options.container = container;
            options.templateFactory = templateFactory;
            repeater(options);
        }

        this.fnHasCache = function() {
            return cacheList;
        }

        this.fnRenderCahce = function() {
            this.fnRender(cacheList, cacheData)
        }

    }

    var AjaxRepeater = components.AjaxRepeater = function ($element, repeater) {
        var self = this;
        self.getList = function (data) {
            var list = data;
            var ajaxOptions = ajax.getOptions($element);
            if (ajaxOptions.dataField) {
                list = data[ajaxOptions.dataField];
            }
            return list;
        }

        self.getAjaxOptions = function () {
            return ajax.getOptions($element);
        }

        self.getRepeater = function () {
            return repeater;
        }

        self.reload = function () {
            var ajaxOptions = ajax.getOptions($element);
            $element.trigger("yulu.ajax.begin", [ajaxOptions]);

            ajaxOptions.success = function (data, textStatus, jqXHR ) {
                $element.trigger("yulu.ajax.success", [data, textStatus, jqXHR]);
                var list = self.getList(data);
                repeater.fnRender(list, data);
            }
            ajaxOptions.error = function (jqXHR, ajaxSettings, thrownError) {
                $element.trigger("yulu.ajax.error", [jqXHR, ajaxSettings, thrownError]);
            }
            ajaxOptions.complete = function (jqXHR, textStatus ) {
                $element.trigger("yulu.ajax.complete", [jqXHR, textStatus]);
            }
            $.ajax(ajaxOptions);
        }
        $element.trigger("yulu.ui.ajaxrpeater.init", self);
    }

    Repeater.getRepeater = function ($container, config, defaultConfig) {
        var $container = $($container);

        config = jQuery.extend({}, defaultConfig, config);
        var $t = $container.find(config.template).remove().clone();
        if ($t.length == 0) {
            $t = $(config.template);
        }

        if (config.includetag) {
            $t = $("<xyz></xyz>").append($t.clone());
        }
        var container = $container,
            template = $t.html(),
            append = config.append,
            replace = config.replace,
            templateFactory = config.templateFactory;
        var repeater = new Repeater(container, template, append, replace, templateFactory);
        return repeater;
    }

    var Table = components.Table = function ($table) {
        var config = core.getDataOptions($table, "yuluTable");
        var repeater = Repeater.getRepeater($table, config, tableConfig);
        this.fnRender = function (list, data) {
            repeater.fnRender(list, data);
        }
    }

    var AjaxTable = components.AjaxTable = function ($table) {
        AjaxRepeater.call(this, $table, new Table($table));
    }

    var Tree = components.Tree = function($tree) {
        var config = core.getDataOptions($tree, "yuluTree");
        var repeater = Repeater.getRepeater($tree, config, treeConfig);
        this.fnRender = function (list, data) {
            repeater.fnRender(list, data);
        }
    }

    var AjaxTree = components.AjaxTree = function ($tree) {
        AjaxRepeater.call(this, $tree, new Tree($tree));
    }

    var List = components.List = function($list) {
        var config = core.getDataOptions($list, "yuluList");
        var repeater = Repeater.getRepeater($list, config, listConfig);
        this.fnRender = function (list, data) {
            repeater.fnRender(list, data);
        }
    }

    var AjaxList = components.AjaxList = function ($list) {
        AjaxRepeater.call(this, $list, new List($list));
    }

    var table = ui.table = function ($table, list, data) {
        var table = $table.data("yulu-ui-table") || new Table($table);
        $table.data("yulu-ui-table", table);
        table.fnRender(list, data);
        return table;
    }

    var list = ui.list = function ($list, list, data) {
        var _list = $list.data("yulu-ui-list") || new List($list);
        $list.data("yulu-ui-list", _list);
        _list.fnRender(list, data);
        return _list;
    }

    var tree = ui.tree = function ($tree, list, data) {
        var tree = $table.data("yulu-ui-tree") || new Tree($tree);
        $tree.data("yulu-ui-tree", tree);
        tree.fnRender(list, data);
        return tree;
    }

    var ajaxTable = ui.ajaxTable = function ($table) {
        var table = $table.data("yulu-ui-ajax-table") || new AjaxTable($table);
        $table.data("yulu-ui-ajax-table", table);
        return table;
    }

    var ajaxTree = ui.ajaxTree = function ($tree) {
        var tree = $tree.data("yulu-ui-ajax-tree") || new AjaxTree($tree);
        $tree.data("yulu-ui-ajax-tree", tree);
        return tree;
    }

    var ajaxList = ui.ajaxList = function ($list) {
        var list = $list.data("yulu-ui-ajax-list") || new AjaxList($list);
        $list.data("yulu-ui-ajax-list", list);
        return list;
    }

    // 插件机制
    var pluginsList = [];
    var Plugin = plugins.Plugins = function () {
        this.repeaterInit = function () {  }
        this.ajaxRepeaterInit = function () { }
    };

    var registerPlugins = plugins.registerPlugins = function(plugin) {
        if (plugin instanceof Function) {
            pluginsList.push(plugin);
        } else {
            if(console && console.error) {
                console.error("!!! Only support Plugin Constructor instance");
            }
        }
    }

    var installPlugins = plugins.install = function(selector) {
        $(selector).on("yulu.ui.repeater.init", function (event, repeater) {
            $(pluginsList).each(function (index, plugin) {
                new plugin(selector).repeaterInit(repeater)
            });
            event.stopPropagation();
        });
        $(selector).on("yulu.ui.ajaxrpeater.init", function (event, ajaxRepeater) {
            $(pluginsList).each(function (index, plugin) {
                new plugin(selector).ajaxRepeaterInit(ajaxRepeater);
            });
            event.stopPropagation();
        });
    }

    $.fn.extend({
        yuluTable: function(operator) {
            this.each(function () {
                var $self = $(this);
                ajaxTable($self);
            });
            if (typeof(operator) === "string") {
                this.each(function () {
                    var $self = $(this);
                    ajaxTable($self)[operator]();
                });
            }
            return this;
        },
        yuluTree: function(operator) {
            this.each(function () {
                var $self = $(this);
                ajaxTree($self);
            });
            if (typeof(operator) === "string") {
                this.each(function () {
                    var $self = $(this);
                    ajaxTree($self)[operator]();
                });
            }
            return this;
        },
        yuluList: function(operator) {
            this.each(function () {
                var $self = $(this);
                ajaxList($self);
            });
            if (typeof(operator) === "string") {
                this.each(function () {
                    var $self = $(this);
                    ajaxList($self)[operator]();
                });
            }
            return this;
        }
    });


    $(function () {
        $("[data-toggle=yulu-table]").yuluTable();
        $("[data-toggle=yulu-tree]").yuluTree();
        $("[data-toggle=yulu-list]").yuluList();
    });
})(window.jQuery, yulu);

